﻿using SharpDX;
using SharpDX.Direct3D;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using Device = SharpDX.Direct3D11.Device;
using Resource = SharpDX.Direct3D11.Resource;

namespace Ensemble_Windows.Core
{
    /// <summary>
    ///     Direct3D11 Render
    /// </summary>
    public class Direct3D11Render : Direct
    {
        private RenderTargetView _backBufferView1;
        private Device _device;
        private SwapChain _swapChain;

        // ReSharper disable once InconsistentNaming
        private Texture2D _backBuffer { get; set; }

        // ReSharper disable once InconsistentNaming
        // ReSharper disable once ConvertToAutoProperty
        private RenderTargetView _backBufferView
        {
            get { return _backBufferView1; }
            set { _backBufferView1 = value; }
        }

        /// <summary>
        ///     返回Device
        /// </summary>
        public Device Device
        {
            get { return _device; }
        }

        /// <summary>
        ///     返回backbuffer使用于SwapChain
        /// </summary>
        public Texture2D BackBuffer
        {
            get { return _backBuffer; }
        }

        /// <summary>
        ///     返回渲染目标视图使用于SwapChain
        /// </summary>
        public RenderTargetView BackBufferView
        {
            get { return _backBufferView; }
        }

        /// <summary>
        ///     游戏初始化
        /// </summary>
        /// <param name="configuration">配置</param>
        protected override void Initialize(Configuration configuration)
        {
            var desc = new SwapChainDescription
            {
                BufferCount = 1,
                ModeDescription = new ModeDescription(configuration.Width, configuration.Height,
                    new Rational(60, 1), Format.R8G8B8A8_UNorm),
                IsWindowed = true,
                OutputHandle = DisplayHandle,
                SampleDescription = new SampleDescription(1, 0),
                SwapEffect = SwapEffect.Discard,
                Usage = Usage.RenderTargetOutput
            };

            Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.BgraSupport,
                new[] {FeatureLevel.Level_10_0}, desc, out _device, out _swapChain);

            var factory = _swapChain.GetParent<Factory>();
            factory.MakeWindowAssociation(DisplayHandle, WindowAssociationFlags.IgnoreAll);

            _backBuffer = Resource.FromSwapChain<Texture2D>(_swapChain, 0);

            _backBufferView = new RenderTargetView(_device, _backBuffer);
        }

        /// <summary>
        ///     开始绘图
        /// </summary>
        protected override void BeginDraw()
        {
            base.BeginDraw();
            Device.ImmediateContext.Rasterizer.SetViewport(new Viewport(0, 0, Config.Width, Config.Height));
            Device.ImmediateContext.OutputMerger.SetTargets(_backBufferView);
        }

        /// <summary>
        ///     结束绘图
        /// </summary>
        protected override void EndDraw()
        {
            _swapChain.Present(Config.WaitVerticalBlanking ? 1 : 0, PresentFlags.None);
        }
    }
}